import { Context, Schema, h } from 'koishi';
import {} from 'koishi-plugin-adapter-onebot';

declare module 'koishi' {
  interface Tables {
    awc_channel_msgs: {
      channelId: string
      messageId: string
      text: string
      time: number
    }
  }
}


export const name = 'wordcloud-generator';

export const inject = ["database"];

export interface Config {
  maxDbSameChannelMsgCount: number;

  defaultMsgCount: number; 
  wordcloudBackendUrl: string;
  defaultEnableGeminiProcess: boolean;
  defaultWidth: number;
  defaultHeight: number;
  defaultBackgroundColor: string;
  defaultMaxWords: number;
  defaultMinFontSize: number;
  defaultPreferHorizontal: number;

  enableSendVerboseArgMsg: boolean;
  verboseConsoleOutput: boolean; 
  waitIntervalSecond: number; 
  blacklistWords: string[];
}

// Define the schema for your plugin's configuration
export const Config: Schema<Config> = Schema.intersect([
  Schema.object({
    maxDbSameChannelMsgCount: Schema.number()
      .default(300)
      .description("每个频道中存储的最大消息数量，超过此数量将删除最旧的消息。"),
  }).description("数据库配置"),

  Schema.object({
    defaultMsgCount: Schema.number()
      .default(300)
      .description("默认的用来制作词云的最近的消息数量，如果不在awc指令中指定，则使用此值。"),

    wordcloudBackendUrl: Schema.string()
      .default("192.168.31.84:8701")
      .description("词云后端服务的地址 (e.g., http://your_ip:8701)"),
    
    defaultEnableGeminiProcess: Schema.boolean()
      .default(false)
      .description("是否把text在Gemini后端再处理一遍，默认为false。"),

    defaultWidth: Schema.number()
      .default(1920)
      .description("默认词云图片的宽度 (像素)"),

    defaultHeight: Schema.number()
      .default(1080)
      .description("默认词云图片的高度 (像素)"),

    defaultBackgroundColor: Schema.string()
      .default("white")
      .description("默认词云图片的背景颜色 (CSS颜色名或HEX码)"),

    defaultMaxWords: Schema.number()
      .default(3000)
      .min(0)
      .description("默认词云中显示的最大词语数量"),

    defaultMinFontSize: Schema.number()
      .default(2)
      .min(0)
      .description("默认词云中词语的最小字体大小"),

    defaultPreferHorizontal: Schema.number()
      .default(0.6)
      .max(1.0)
      .min(0.0)
      .step(0.01)
      .description("默认词语水平排列的偏好 (0.0-1.0)")
  }).description("词云后端配置"),

  Schema.object({
    enableSendVerboseArgMsg: Schema.boolean()
      .default(false)
      .description("是否在生成词云时发送非常tm详细的参数消息，便于调试和查看当前配置。"),
    verboseConsoleOutput: Schema.boolean()
      .default(false)
      .description("是否在控制台输出详细的调试信息，便于开发和调试。"),

    waitIntervalSecond: Schema.number()
      .default(10)
      .description("等待词云生成的间隔时间（秒），如果超过此时间未生成词云，将发送提示消息。"),
    blacklistWords: Schema.array(String)
      .default(["awc"])
      .description("黑名单词语列表，包含这些词语的消息将不会被记录或生成词云。")
  }).description("koishi前端配置")

]);
 

export function apply(ctx: Context, config: Config) {
  ctx.model.extend('awc_channel_msgs', {
    channelId: 'string',
    messageId: 'string',
    text: 'string',
    time: 'integer',
  }, {
    primary: ['channelId', 'messageId'],
  });

  if (!ctx.database) {
    ctx.logger.warn("数据库服务未加载，wordcloud-generator 插件将无法正常工作。");
    return;
  }

  const backendUrl = `http://${config.wordcloudBackendUrl}/wordcloud`; 


  ctx.on('message', async (session) => {
    if( !session.channelId ){
      ctx.logger.error('channelid不存在');
      return;
    }

    if ( !session.event.message?.elements ){
      ctx.logger.error(`消息元素不存在`);
      return;
    }

    if ( session.userId == session.bot.selfId ){
      return;
    }

    const texts: string[] = [];
    for ( const e of session.event.message.elements ){
      if ( e.type === 'text' && e.attrs.content ) {
        texts.push(e.attrs.content);
      }
    }
    const messageText = texts.join(' ');
    
    if ( config.verboseConsoleOutput ){
      if ( !messageText || messageText.length === 0 ) {
        ctx.logger.error(`消息不包含文本，无法生成词云. 消息开头: ${session.event.message.content.slice(0, 60)}`);
        return;
      }
    }

  
    await ctx.database.create('awc_channel_msgs', {
      channelId: session.channelId,
      messageId: session.messageId,
      text: messageText,
      time: Date.now()
    })
    // await session.send(`[debug] insert, text: ${messageText.slice(0,60)}`);

    const cnt = (await ctx.database.select('awc_channel_msgs')
      .where({ channelId: session.channelId })
      .execute()).length;
    
    const MAX_MSG_COUNT = config.maxDbSameChannelMsgCount;
    if ( cnt > MAX_MSG_COUNT ){
      const overflowCount = cnt - MAX_MSG_COUNT;
      if ( config.verboseConsoleOutput )
        ctx.logger.info(`频道 ${session.channelId} 的消息数量超过限制，删除最旧的 ${overflowCount} 条消息。`);

      const oldestMsgs = await ctx.database
        .select('awc_channel_msgs')
        .where( { channelId: session.channelId } )
        .orderBy('time', 'asc')
        .limit(overflowCount)
        .execute();
      
      const msgIdsToDelete = oldestMsgs.map(entry => entry.messageId);
      await ctx.database.remove('awc_channel_msgs', { messageId: msgIdsToDelete });

    }

  })

  // Command to generate a word cloud
  ctx.command('awc', '\t根据群u最近的文字消息 或者 指定的文本 生成词云图')
    .alias('awa_wordcloud', '词云') // Add aliases for convenience
    .option('verbose', '-V, --verbose \t是否发送详细的参数消息，默认为false')
    .option('count', '-c, --count <count:number> \t最近消息条数，默认为300条')
    .option('text', '-t, --text <text:string> \t指定词云文本，如果不传，则使用最近的群u聊天')
    .option('enable_gemini_process', '-g, --gemini \t是否在后端用Gemini再处理一遍文本，默认为false')
    .option('width', '-W, --width <width:number> \t词云图片宽度，默认为1920')
    .option('height', '-H, --height <height:number> \t词云图片高度，默认值为1080')
    .option('bg', '--bg <color:string> \t词云图片背景颜色， 默认为white')
    .option('maxwords', '-m, -max-words <maxwords:number> \t词云中显示的最大词语数量， 默认为3000')
    .option('minfont', '-f, --min-font <minfont:number> \t词云图片中的最小文字的尺寸， 默认为2')
    .option('prefer_horizontal', '-p, --prefer_horizontal <prefer_horizontal:number> \t一个介于0.0和1.0之间的数字，表示词语水平排列的偏好，0.0表示完全垂直，1.0表示完全水平，默认值为0.6')
    .action(async ({ session, options }) => {

      try{
        let awc_count: number;
        awc_count = options.count ? options.count : config.defaultMsgCount;
        awc_count = Math.min(awc_count, config.maxDbSameChannelMsgCount);

        let awc_text;
        // let awc_text = options.text ? options.text : joinedText;
        if ( options.text ){
          awc_text = options.text;
        } else {
          const recentMsgs = await ctx.database
          .get(
            'awc_channel_msgs', 
            {
              channelId: session.channelId,
            },
            {
              sort: { time: 'desc' },
              limit: awc_count
            }
          )
          const joinedText = recentMsgs.map( o=> o.text ).join(',');
          awc_text = joinedText;

          for (const word of config.blacklistWords) {
            const regex = new RegExp(word, 'gi');  // 不区分大小写
            awc_text = awc_text.replace(regex, '');
          }
        }

        let awc_enableGeminiProcess = options.enable_gemini_process ? options.enable_gemini_process : config.defaultEnableGeminiProcess;
        let awc_width = options.width ? options.width : config.defaultWidth;
        let awc_height = options.height ? options.height : config.defaultHeight;
        let awc_bg = options.bg ? options.bg : config.defaultBackgroundColor;
        let awc_maxwords = options.maxwords ? options.maxwords : config.defaultMaxWords;
        let awc_minfont = options.minfont ? options.minfont : config.defaultMinFontSize;
        let awc_prefer_horizontal = options.prefer_horizontal
          ? options.prefer_horizontal 
          : config.defaultPreferHorizontal;
        
        let argMsg = `[awa_wordcloud] 🕰️ 正在生成中.....别急\n`;

        let isSendVerboseArgMsg = options.verbose || config.enableSendVerboseArgMsg;
        if ( isSendVerboseArgMsg ){
          argMsg += `\t 🔢 awc_count[最近消息条数] = ${awc_count} \t (${options.count?'':'没传，使用默认值'}) \n`;
          const MAX_ARG_TEXT_LENG = 100;
          argMsg += `\t 📝 awc_text[词云文本] = ${awc_text.slice(0,MAX_ARG_TEXT_LENG)} ${awc_text.length>MAX_ARG_TEXT_LENG?'...':''} \t (${options.text?'':'没传，使用默认值'}) \n`;
          argMsg += `\t ⚙️ awc_enable_gemini_process[是否Gemini处理] = ${options.enable_gemini_process ? '是' : '否'} \t (${options.enable_gemini_process?'':'没传，使用默认值'}) \n`;
          argMsg += `\t 📐 awc_width[图片宽度] = ${awc_width} \t (${options.width?'':'没传，使用默认值'}) \n`;
          argMsg += `\t 📐 awc_height[图片高度] = ${awc_height} \t (${options.height?'':'没传，使用默认值'}) \n`;
          argMsg += `\t 🎨 awc_bg[背景颜色] = ${awc_bg} \t (${options.bg?'':'没传，使用默认值'}) \n`;
          argMsg += `\t 🔤 awc_maxwords[最大单词数] = ${awc_maxwords} \t (${options.maxwords?'':'没传，使用默认值'}) \n`;
          argMsg += `\t 🔤 awc_minfont[最小字体尺寸] = ${awc_minfont} \t (${options.minfont?'':'没传，使用默认值'}) \n`;
          argMsg += `\t ↔️ awc_prefer_horizontal[水平排列偏好] = ${awc_prefer_horizontal} \t (${options.prefer_horizontal?'':'没传，使用默认值'}) \n`;
        }

        const argMsgId = await session.send(h.quote(session.messageId) + argMsg);


        const requestBody = {
          text: awc_text,
          enable_gemini_process: awc_enableGeminiProcess ? true : false,
          width: awc_width,
          height: awc_height,
          background_color: awc_bg,
          max_words: awc_maxwords,
          min_font_size: awc_minfont,
          prefer_horizontal: awc_prefer_horizontal,
        }
        const wcRes = await ctx.http.post(
          backendUrl,
          // { text: joinedText }
          requestBody
        )
        const wcAns = wcRes.image;


        let resolved = false;
        let waitCounter = 1;
        let lastWaitMsgId = argMsgId;
        const waitInterval = setInterval(async () => {
          if (resolved) {
            clearInterval(waitInterval);
            return;
          }

          await session.bot.deleteMessage(session.channelId, String(lastWaitMsgId));

          const newMsg = await session.send(h.quote(session.messageId) + `🕰️ 词云生成中...已等待 ${waitCounter * config.waitIntervalSecond}s，请耐心稍候`);
          lastWaitMsgId = newMsg;
          waitCounter += 1;

        }, config.waitIntervalSecond * 1000);


        await session.send(h.image(wcAns));
        resolved = true;
        await session.bot.deleteMessage(session.channelId, String(lastWaitMsgId));

      } catch (err){
        ctx.logger.error(`[awa_wordcloud] 未知错误：${err}`);
      }

    });

}